/*
 * Copyright (C) 2010-2012 Enrique Lara (enrique.posix2.lara@gmail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package app.transitalarm;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.TimePickerDialog;

import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;

import android.media.Ringtone;

import android.os.Bundle;

import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;

import android.preference.Preference.OnPreferenceChangeListener;

import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.preference.RingtonePreference;

import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;
import android.widget.TimePicker;

import app.transitalarm.RepeatPreference.OnRepeatChangedObserver;

import app.transitalarm.model.Agency;
import app.transitalarm.model.Alarm;
import app.transitalarm.model.App;

import app.transitalarm.provider.Tables.Alarms;

import app.transitalarm.util.Constants;
import app.transitalarm.util.Log;

import app.transitalarm.view.DaysOfWeek;

public class AlarmEditor extends PreferenceActivity {
    public static final int MENU_ITEM_SAVE = Menu.FIRST;
    public static final int MENU_ITEM_DELETE = Menu.FIRST + 1;
    public static final int MENU_ITEM_REVERT = Menu.FIRST + 2;
    public static final int MENU_ITEM_DISCARD = Menu.FIRST + 3;
    public static final int MENU_ITEM_START_NOW = Menu.FIRST + 4;
    public static final int MENU_ITEM_VIEW = Menu.FIRST + 5;
    private static final int STATE_UNKNOWN = 0;
    private static final int STATE_EDIT = 1;
    private static final int STATE_INSERT = 3;
    private static final String TAG = "AlarmEditor";
    private static final int DIALOG_TIME = 1;
    private int state = STATE_UNKNOWN;
    protected Alarm a = null;
    protected Agency agency = null;
    private CheckBoxPreference enabledPref;
    private Preference timePref;
    private RepeatPreference repeatPref;
    protected ListPreference routePref;
    protected ListPreference directionPref;
    protected Preference stationPref;
    private ListPreference timeMaxPref;
    private ListPreference timeMinPref;
    private RingtonePreference ringtonePref;
    private CheckBoxPreference vibratePref;
    private EditTextPreference labelPref;

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final Intent intent = getIntent();

        final String action = intent.getAction();

        if (Constants.ACTION_EDIT.equals(action) || Constants.ACTION_EDIT_STOP_FIRST.equals(action)) {
            state = STATE_EDIT;

            a = App.loadAlarm(intent.getData(), this);

            agency = a.getAgency();
        } else if (Constants.ACTION_INSERT.equals(action) || Constants.ACTION_INSERT_STOP_FIRST.equals(action)) {
            state = STATE_INSERT;

            final int agencyId = getIntent().getExtras().getInt(Alarms.AGENCY_ID);
            agency = App.getAgency(agencyId, this);

            a = agency.newAlarm(intent.getData());

            if (a == null) {
                Log.e(TAG, "Failed to insert new note into " + intent.getData());
                finish();
            }

            setResult(RESULT_OK, new Intent().setAction(a.getUri().toString()));
        } else {
            Log.e(TAG, "Unknown action, exiting");
            finish();

            return;
        }

        initPreferences();
        initButtons();
    }

    private void initPreferences() {
        addPreferencesFromResource(agency.getPreferenceId());

        enabledPref = (CheckBoxPreference) findPreference(Alarms.ENABLED);
        enabledPref.setChecked(a.isEnabled());
        enabledPref.setOnPreferenceChangeListener(new EnabledPrefListener());
        timePref = findPreference("time");

        repeatPref = (RepeatPreference) findPreference(Alarms.DAYS_IN_WEEK);
        repeatPref.setOnRepeatChangedObserver(new RepeatPrefListener());

        initVectorPreferences();

        timeMaxPref = (ListPreference) findPreference(Alarms.TIME_MAX);
        timeMaxPref.setValue(Integer.toString(a.getMaxTime()));
        timeMaxPref.setOnPreferenceChangeListener(new TimeMaxPrefListener());

        timeMinPref = (ListPreference) findPreference(Alarms.TIME_MIN);
        timeMinPref.setValue(Integer.toString(a.getMinTime()));
        timeMinPref.setOnPreferenceChangeListener(new TimeMinPrefListener());

        labelPref = (EditTextPreference) findPreference(Alarms.LABEL);
        labelPref.setText(a.getLabel());
        labelPref.setOnPreferenceChangeListener(new LabelPrefListener());

        ringtonePref = (RingtonePreference) findPreference(Alarms.RINGTONE);

        final Ringtone ringtone = a.getRingtoneObj();

        if (ringtone != null) {
            final SharedPreferences prefs = ringtonePref.getPreferenceManager().getSharedPreferences();
            prefs.edit().putString(Alarms.RINGTONE, a.getRingtone()).commit();
        }

        ringtonePref.setOnPreferenceChangeListener(new RingtonePrefListener());

        vibratePref = (CheckBoxPreference) findPreference(Alarms.VIBRATE);
        vibratePref.setOnPreferenceChangeListener(new VibratePrefListener());
    }

    protected void initVectorPreferences() {
        final String[] routes = agency.getRouteNames();
        final String[] routeCodes = agency.getRouteCodes();

        routePref = (ListPreference) findPreference(Alarms.ROUTE);
        routePref.setEntries(routes);
        routePref.setEntryValues(routeCodes);
        routePref.setValue(a.getRouteCode());
        routePref.setOnPreferenceChangeListener(new RoutePrefListener());

        directionPref = (ListPreference) findPreference(Alarms.DIRECTION);
        directionPref.setValue(a.getDirection());
        directionPref.setOnPreferenceChangeListener(new DirectionPrefListener());

        stationPref = findPreference("station"); //Alarms.STATION_NAME);

        final ListPreference stationListPref = (ListPreference) stationPref;
        stationListPref.setValue(a.getStopCode());
        stationListPref.setOnPreferenceChangeListener(new StationPrefListener());
    }

    private void initButtons() {
        if (state == STATE_EDIT) {
            setContentView(R.layout.alarm_edit);
        } else if (state == STATE_INSERT) {
            setContentView(R.layout.alarm_insert);
        } else {
            return;
        }

        Button b = (Button) findViewById(R.id.done);
        b.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(final View v) {
                    done();
                }
            });
        b = (Button) findViewById(R.id.run);
        b.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(final View v) {
                    run();
                }
            });

        if (state == STATE_EDIT) {
            b = (Button) findViewById(R.id.delete);
            b.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(final View v) {
                        AlarmEditor.this.delete();
                    }
                });
        } else if (state == STATE_INSERT) {
            b = (Button) findViewById(R.id.cancel);
            b.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(final View v) {
                        AlarmEditor.this.cancel();
                    }
                });
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (a != null) {
            if (state == STATE_EDIT) {
                setTitle(getText(R.string.edit_alarm));
            } else if (state == STATE_INSERT) {
                setTitle(getText(R.string.add_alarm));
            }

            updateAll();

            //			Toast.makeText(this, "Active=" + a.isActiveToday(), Toast.LENGTH_LONG).show();
        } else {
            throw new IllegalStateException("No Alarm Available.");
        }
    }

    private void updateAll() {
        updateEnabled();
        updateTime();
        updateRepeat();

        updateStation();
        updateRoute();
        updateDirection();
        updateMaxTime();
        updateMinTime();

        updateRingtone();
        vibratePref.setChecked(a.isVibrate());
        labelPref.setSummary(a.getLabel());
    }

    private void refreshAlarm() {
        a = App.loadAlarm(a.getUri(), this);
        agency = a.getAgency();
    }

    private void updateEnabled() {
        enabledPref.setChecked(a.isEnabled());

        if (a.isEnabled()) {
            enabledPref.setTitle(R.string.alarm_disable);
        } else {
            enabledPref.setTitle(R.string.alarm_enable);
        }
    }

    private void updateTime() {
        timePref.setSummary(a.getTimeStr());
    }

    private void updateRepeat() {
        repeatPref.setSummary(a.getRepeatStr());
    }

    protected void updateStation() {
        final String[] stations = agency.getStopNames(a.getRouteCode());
        final String[] stationCodes = agency.getStopCodes(a.getRouteCode());

        final ListPreference stationListPref = (ListPreference) stationPref;
        stationListPref.setEntries(stations);
        stationListPref.setEntryValues(stationCodes);
        stationListPref.setSummary(a.getStopName());
    }

    protected void updateRoute() {
        routePref.setSummary(a.getRoute().getName());
    }

    protected void updateDirection() {
        final String[] directions = a.getRoute().getDirectionNames();
        final String[] directionCodes = a.getRoute().getDirectionCodes();

        directionPref.setEntries(directions);
        directionPref.setEntryValues(directionCodes);
        directionPref.setSummary(a.getDirectionName());
    }

    private void updateMaxTime() {
        timeMaxPref.setSummary(Integer.toString(a.getMaxTime()));
    }

    private void updateMinTime() {
        timeMinPref.setSummary(Integer.toString(a.getMinTime()));
    }

    private void updateRingtone() {
        final Ringtone ringtone = a.getRingtoneObj();

        if (ringtone != null) {
            ringtonePref.setSummary(ringtone.getTitle(this));
        } else {
            ringtonePref.setSummary(R.string.silent);
        }
    }

    @Override
    public boolean onPreferenceTreeClick(final PreferenceScreen preferenceScreen, final Preference preference) {
        if (preference == timePref) {
            showDialog(DIALOG_TIME);
        }

        return super.onPreferenceTreeClick(preferenceScreen, preference);
    }

    @Override
    protected void onPause() {
        super.onPause();

        // The user is going somewhere else, so make sure their current
        // changes are safely saved away in the provider.
        if ((a != null) && a.isDirty()) {
            a.update();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(final Menu menu) {
        super.onCreateOptionsMenu(menu);

        menu.add(0, MENU_ITEM_VIEW, 0, R.string.view_alarm).setShortcut('4', 'v').setIcon(android.R.drawable.ic_menu_view);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(final MenuItem item) {
        switch (item.getItemId()) {
            case MENU_ITEM_SAVE:
                done();

                break;

            case MENU_ITEM_DELETE:
                delete();

                break;

            case MENU_ITEM_DISCARD:
                cancel();

                break;

            case MENU_ITEM_REVERT:

                if (a != null) {
                    if (state == STATE_EDIT) {
                        refreshAlarm();
                        updateAll();
                    } else if (state == STATE_INSERT) {
                        delete();
                        finish();
                    }
                }

                break;

            case MENU_ITEM_START_NOW:
                run();

                break;

            case MENU_ITEM_VIEW:
                view();

                break;

            default:
        }

        return super.onOptionsItemSelected(item);
    }

    private void done() {
        setResult(RESULT_OK);
        finish();
    }

    private void run() {
        if (a.isDirty()) {
            final AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle(R.string.prompt_save_now);
            builder.setMessage(R.string.run_now_prompt_save_dia).setCancelable(false).setPositiveButton(R.string.save, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(final DialogInterface dialog, final int id) {
                        dialog.dismiss();

                        a.updateQuiet();
                        a.startPollingNow();
                    }
                }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(final DialogInterface dialog, final int id) {
                        dialog.dismiss();
                    }
                });
            builder.show();
        } else {
            a.startPollingNow();
        }
    }

    private void view() {
        if (a.isDirty()) {
            final AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle(R.string.prompt_save_now);
            builder.setMessage(R.string.view_prompt_save_dia).setCancelable(false).setPositiveButton(R.string.save, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(final DialogInterface dialog, final int id) {
                        dialog.dismiss();

                        a.updateQuiet();
                        a.gotoView();
                    }
                }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(final DialogInterface dialog, final int id) {
                        dialog.dismiss();
                    }
                });
            builder.show();
        } else {
            a.gotoView();
        }
    }

    private void cancel() {
        if ((a != null) && (state == STATE_INSERT)) {
            a.delete();
            a = null;
        }

        setResult(RESULT_CANCELED);
        finish();
    }

    private void delete() {
        if (a != null) {
            final AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setMessage(R.string.confirm_delete_alarm).setTitle(R.string.delete_alarm).setCancelable(false).setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(final DialogInterface dialog, final int id) {
                        a.delete();
                        a = null;
                        dialog.dismiss();
                        AlarmEditor.this.finish();
                    }
                }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(final DialogInterface dialog, final int id) {
                        dialog.dismiss();
                    }
                });
            builder.show();
        }
    }

    @Override
    protected Dialog onCreateDialog(final int id) {
        switch (id) {
            case DIALOG_TIME:
                return new TimePickerDialog(this, new TimePickerDialog.OnTimeSetListener() {
                        @Override
                        public void onTimeSet(final TimePicker view, final int hourOfDay, final int minute) {
                            a.setHour(hourOfDay);
                            a.setMinute(minute);
                            a.update();
                            updateTime();
                        }
                    }, a.getHour(), a.getMinute(), android.text.format.DateFormat.is24HourFormat(this));

            default:

            // Ignore.
        }

        return null;
    }

    // ------------------ START Listeners
    private final class EnabledPrefListener implements OnPreferenceChangeListener {
        @Override
        public boolean onPreferenceChange(final Preference preference, final Object newValue) {
            a.setEnabled(Boolean.TRUE.equals(newValue));
            a.update();
            updateEnabled();

            return true;
        }
    }

    private final class RepeatPrefListener implements OnRepeatChangedObserver {
        @Override
        public void onRepeatChanged(final boolean[] vals) {
            a.setRepeat(DaysOfWeek.toInt(vals));
            a.update();
            updateRepeat();
        }

        @Override
        public DaysOfWeek getDaysOfWeek() {
            return new DaysOfWeek(a.getRepeat());
        }
    }

    private final class TimeMaxPrefListener implements OnPreferenceChangeListener {
        @Override
        public boolean onPreferenceChange(final Preference preference, final Object newValue) {
            a.setMaxTime(Integer.parseInt(newValue.toString()));
            a.updateQuiet();
            updateMaxTime();

            return true;
        }
    }

    private final class TimeMinPrefListener implements OnPreferenceChangeListener {
        @Override
        public boolean onPreferenceChange(final Preference preference, final Object newValue) {
            a.setMinTime(Integer.parseInt(newValue.toString()));
            updateMinTime();

            return true;
        }
    }

    private final class LabelPrefListener implements OnPreferenceChangeListener {
        @Override
        public boolean onPreferenceChange(final Preference preference, final Object newValue) {
            a.setLabel(newValue.toString());
            labelPref.setSummary(a.getLabel());

            return true;
        }
    }

    private final class RingtonePrefListener implements OnPreferenceChangeListener {
        @Override
        public boolean onPreferenceChange(final Preference preference, final Object newValue) {
            a.setRingtone(newValue.toString());
            updateRingtone();

            return true;
        }
    }

    private final class VibratePrefListener implements OnPreferenceChangeListener {
        @Override
        public boolean onPreferenceChange(final Preference preference, final Object newValue) {
            a.setVibrate(Boolean.TRUE.equals(newValue));

            return true;
        }
    }

//-- Vector Pref Listeners
    private final class RoutePrefListener implements OnPreferenceChangeListener {
        @Override
        public boolean onPreferenceChange(final Preference preference, final Object newValue) {
            a.setRoute(newValue.toString());
            updateRoute();

            a.setDirection("");
            updateDirection();

            a.setStop("");
            updateStation();

            return true;
        }
    }

    private final class DirectionPrefListener implements OnPreferenceChangeListener {
        @Override
        public boolean onPreferenceChange(final Preference preference, final Object newValue) {
            a.setDirection(newValue.toString());
            updateDirection();

            return true;
        }
    }

    private final class StationPrefListener implements OnPreferenceChangeListener {
        @Override
        public boolean onPreferenceChange(final Preference preference, final Object newValue) {
            a.setStop(newValue.toString());
            updateStation();

            return true;
        }
    }

    // ------------------ END Listeners
}
